home *** CD-ROM | disk | FTP | other *** search
- { A set of routines for text window manipulation
- By Bela Lubkin
- Borland International Technical Support
- 1/10/85
- (For PC-DOS Turbo Pascal version 2 or greater)
-
- Notes: These routines cause extreme blinking on the color monitor. If anyone
- modifies them to decrease this blinking, please upload your modified
- routines to the Borland SIG on CompuServe - GO BOR
-
- REMEMBER to dispose of your windows, or you will quickly run out of
- heap space. Procedure DRestoreWindow restores a window to the screen
- and then disposes of the window; procedure DisposeWindow disposes of
- a window. DO NOT USE Turbo's built in Dispose procedure on a window;
- windows are allocated with GetMem and must be disposed with FreeMem. }
-
- Type
- XTCoord=1..80; { X Text coordinate }
- YTCoord=1..25; { Y Text coordinate }
- XTCoord0=0..80; { X Text coordinate + 0 for nothing }
- YTCoord0=0..25; { Y Text coordinate + 0 for nothing }
- WindowRec=Record
- XSize: XTCoord;
- YSize: YTCoord;
- XPosn: XTCoord;
- YPosn: YTCoord;
- Contents: Array [0..1999] Of Integer;
- End;
- WindowPtr=^WindowRec;
-
- Var
- ScreenBase: Integer; { Segment address of the screen: $B000 for monochrome,
- $B800 for color }
- WindowXLo: XTCoord;
- WindowYLo: YTCoord;
- WindowXHi: XTCoord;
- WindowYHi: YTCoord;
-
- Procedure TurboWindow(XL: XTCoord; YL: YTCoord; XH: XTCoord; YH: YTCoord);
- { This procedure provides an entry to Turbo's built in Window procedure }
- Begin
- Window(XL,YL,XH,YH);
- End;
-
- Procedure Window(XL: XTCoord; YL: YTCoord; XH: XTCoord; YH: YTCoord);
- { This procedure replaces Turbo's built in Window procedure. It calls the
- original Window procedure, and also keeps track of the window boundaries. }
-
- Begin
- TurboWindow(XL,YL,XH,YH);
- WindowXLo:=XL;
- WindowYLo:=YL;
- WindowXHi:=XH;
- WindowYHi:=YH;
- End;
-
- Function SaveWindow(XLow: XTCoord; YLow: YTCoord;
- XHigh: XTCoord; YHigh:YTCoord): WindowPtr;
- { Allocate a WindowRec of the precise size needed to save the window, then
- fill it with the text that is in the window XLow..XHigh, YLow..YHigh.
- Return a pointer to this WindowRec. }
-
- Var
- SW: WindowPtr;
- I: Integer;
- XS: XTCoord;
- YS: YTCoord;
-
- Begin
- XS:=XHigh-XLow+1;
- YS:=YHigh-YLow+1;
- GetMem(SW,2*XS*YS + 4);
- { Allocate 2 bytes for each screen position, + 4 for size and position }
- With SW^ Do
- Begin
- XSize:=XS;
- YSize:=YS;
- XPosn:=XLow;
- YPosn:=YLow;
- For I:=0 To YSize-1 Do
- Move(Mem[ScreenBase:((YPosn+I-1)*80+XPosn-1) Shl 1],
- Contents[I*XSize],XSize Shl 1);
- { For each line of the window,
- Move XSize*2 bytes (1 for char, 1 for attribute) into the Contents
- array. Leave no holes in the array. }
- End;
- SaveWindow:=SW;
- End;
-
- Function SaveCurrentWindow: WindowPtr;
- Begin
- SaveCurrentWindow:=SaveWindow(WindowXLo,WindowYLo,WindowXHi,WindowYHi);
- End;
-
- Procedure RestoreWindow(WP: WindowPtr; XPos: XTCoord0; YPos: YTCoord0);
- { Given a pointer to a WindowRec, restore the contents of the window. If
- XPos or YPos is 0, use the XPosn or YPosn that the window was originally
- saved with. If either is nonzero, use it. Thus a window can be restored
- exactly with RestoreWindow(wp,0,0); or its upper left corner can be
- placed at (2,3) with RestoreWindow(wp,2,3); }
-
- Var
- I: Integer;
-
- Begin
- With WP^ Do
- Begin
- If XPos=0 Then XPos:=XPosn;
- If YPos=0 Then YPos:=YPosn;
- For I:=0 To YSize-1 Do
- Move(Contents[I*XSize],
- Mem[ScreenBase:2*((YPos+I-1)*80+XPos-1)],XSize*2);
- { For each line of the window,
- Move XSize*2 bytes (1 for char, 1 for attribute) from the Contents
- array onto the screen. }
- End;
- End;
-
- Procedure DisposeWindow(Var WP: WindowPtr);
- { Dispose of a WindowPtr. The built in procedure Dispose cannot be used,
- because it will deallocate SizeOf(WindowRec) bytes, even though less may
- have been allocated. }
-
- Begin
- With WP^ Do FreeMem(WP,2*XSize*YSize+4);
- WP:=Nil;
- End;
-
- Procedure DRestoreWindow(Var WP: WindowPtr; XPos: XTCoord0; YPos: YTCoord0);
- { Restore the contents of a window, then dispose of the saved image }
-
- Begin
- RestoreWindow(WP, XPos, YPos);
- DisposeWindow(WP);
- End;
-
- Procedure DRestoreCurrentWindow(Var WP: WindowPtr;
- XPos: XTCoord0; YPos: YTCoord0);
- { Restore the contents of a window, set the current window to fit the restored
- window, and dispose of the saved image. A similar procedure
- RestoreCurrentWindow could be written by changing DRestoreWindow to
- RestoreWindow in the last line of the procedure, but I have assumed that
- when you select a window area, you are going to modify it, and not want the
- old image }
-
- Begin
- With WP^ Do
- Begin
- If XPos=0 Then XPos:=XPosn;
- If YPos=0 Then YPos:=YPosn;
- Window(XPos,YPos,XPos+XSize-1,YPos+YSize-1);
- End;
- DRestoreWindow(WP, XPos, YPos);
- End;
-
- Procedure DetermineDisplay;
- { Set ScreenBase to $B000 or $B800, depending on which display is in use.
- A side effect is that the cursor is left at (1,1) on the screen. }
-
- Var
- M,C: Integer;
- T: Byte;
-
- Begin
- M:=MemW[$B000:0];
- C:=MemW[$B800:0];
- T:=64;
- If (Hi(M)=T) Or (Hi(C)=T) Then T:=65;
- If (Hi(M)=T) Or (Hi(C)=T) Then T:=66;
- GotoXY(1,1);
- Write(Chr(T));
- GotoXY(1,1);
- If Mem[$B000:0]=T Then ScreenBase:=$B000
- Else ScreenBase:=$B800;
- MemW[$B000:0]:=M;
- MemW[$B800:0]:=C;
- End;
-
- { Example program -- remove next line to enable }
- Var
- X,Y: Byte;
- W,W2: WindowPtr;
- Ch: Char;
-
- Begin
- DetermineDisplay; { Set ScreenBase according to the display in use }
- For Y:=1 To 1999 Do
- Write(Chr(Random(95)+32)); { Fill the screen with junk }
- W:=SaveWindow(1,1,80,25); { Save the whole screen }
- Read(Kbd,Ch);
- ClrScr; { Clear it }
- Read(Kbd,Ch);
- DRestoreWindow(W,0,0); { Restore it }
- Read(Kbd,Ch);
- Window(5,4,53,23);
- W:=SaveCurrentWindow; { Save a medium sized window }
- ClrScr; { Wipe that window }
- Read(Kbd,Ch);
- RestoreWindow(W,0,0); { And restore it }
- Window(1,1,80,25);
- Read(Kbd,Ch);
- W2:=SaveWindow(2,2,10,10); { Save a small window }
- ClrScr;
- Read(Kbd,Ch);
- For X:=1 To 72 Do { Restore it in a square around the edges of }
- RestoreWindow(W2,X,1); { the screen }
- For Y:=2 To 17 Do
- RestoreWindow(W2,72,Y);
- For X:=71 DownTo 1 Do
- RestoreWindow(W2,X,17);
- For Y:=16 DownTo 1 Do
- RestoreWindow(W2,1,Y);
- Read(Kbd,Ch);
- DisposeWindow(W2);
- DRestoreWindow(W,0,0); { Restore the medium sized window saved earlier }
- End.
- (**)